//package com.chenl.consumer.DEMOS.幂等注解;
//
//import com.alibaba.fastjson2.JSONObject;
//import lombok.extern.slf4j.Slf4j;
//import org.apache.commons.lang.StringUtils;
//import org.aspectj.lang.ProceedingJoinPoint;
//import org.aspectj.lang.annotation.Around;
//import org.aspectj.lang.annotation.Aspect;
//import org.aspectj.lang.annotation.Pointcut;
//import org.aspectj.lang.reflect.MethodSignature;
//import org.slf4j.MDC;
//import org.springframework.beans.factory.BeanFactory;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.context.expression.BeanFactoryResolver;
//import org.springframework.context.expression.MethodBasedEvaluationContext;
//import org.springframework.core.DefaultParameterNameDiscoverer;
//import org.springframework.core.ParameterNameDiscoverer;
//import org.springframework.data.redis.core.RedisTemplate;
//import org.springframework.expression.BeanResolver;
//import org.springframework.expression.ExpressionParser;
//import org.springframework.expression.spel.standard.SpelExpressionParser;
//import org.springframework.expression.spel.support.StandardEvaluationContext;
//
//import javax.annotation.Resource;
//import java.lang.reflect.Method;
//import java.lang.reflect.Parameter;
//import java.util.ArrayList;
//import java.util.List;
//import java.util.concurrent.TimeUnit;
//
///**
// * 防重提交,redis版本
// */
//@Aspect
//@Slf4j
////@Component
//public class IdempotentMethodAspect {
//    @Autowired
//    BeanFactory beanFactory;
//
//    private static final ParameterNameDiscoverer NAME_DISCOVERER = new DefaultParameterNameDiscoverer();
//    private static final ExpressionParser PARSER = new SpelExpressionParser();
//
//    @Resource(name = "MyRedisTemplate")
//    RedisTemplate redisTemplate;
//
//    @Pointcut("@annotation(com.chenl.consumer.DEMOS.幂等注解.Idempotent)")
//    public void webLog() {
//    }
//
//    @Around("webLog()")
//    public Object interceptor(ProceedingJoinPoint joinPoint) throws Throwable {
//        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
//        Method method = signature.getMethod();
//        Idempotent imdmpotent = method.getAnnotation(Idempotent.class);
//        String key = getKey(imdmpotent.key(), method, joinPoint.getArgs());
//        long expire = imdmpotent.expire();
//        String traceId = MDC.get("traceId");
//        if (StringUtils.isNotBlank(traceId)) {
//            String keyWrapper = "Idempotent:" + traceId + "|" + imdmpotent.message() + ":" + key;
//            log.info("幂等方法拦截---请求开始,当前请求traceId为：{}，keyWrapper:{}",traceId , keyWrapper);
//            if (StringUtils.isNotBlank(keyWrapper)) {
//                if (redisTemplate.opsForValue().get(keyWrapper) != null) {
//                    log.error("幂等方法拦截---不执行，key:{}", keyWrapper);
//                    throw new RuntimeException("幂等拦截请求不执行！");
//
//                }
//                log.info("幂等方法拦截---放行");
//            }
//            Object[] args = joinPoint.getArgs();
//            Object retVal;
//            try {
//                retVal = joinPoint.proceed(args);
//            } catch (Exception e) {
//                throw new RuntimeException(e);
//            }
//            redisTemplate.opsForValue().set(keyWrapper, keyWrapper, expire, TimeUnit.MINUTES);
//            return retVal;
//        }else {
//          log.error("traceId为空,幂等拦截不生效");
//            Object[] args = joinPoint.getArgs();
//            Object retVal;
//            try {
//                retVal = joinPoint.proceed(args);
//            } catch (Exception e) {
//                throw new RuntimeException(e);
//            }
//            return retVal;
//        }
//
//    }
//
//    private String getKey(String keyExpress, Method method, Object[] args){
////        return JSONObject.toJSONString(args);
//        SpelExpressionParser parser = new SpelExpressionParser();
//        StandardEvaluationContext context = new StandardEvaluationContext();
//        Parameter[] parameters = method.getParameters();
//        for(int i = 0; i < parameters.length; i++){
//            context.setVariable(parameters[i].getName(), args[i]);
//        }
//        return JSONObject.toJSONString(parser.parseExpression(keyExpress).getValue(context));
//    }
//
//    protected String getKeys(String[] definitionKeys, Method method, Object[] parameterValues) {
//         BeanResolver beanResolver= new BeanFactoryResolver(beanFactory);;
//        StandardEvaluationContext context = new MethodBasedEvaluationContext((Object)null, method, parameterValues, NAME_DISCOVERER);
//        context.setBeanResolver(beanResolver);
//        List<Object> definitionKeyList = new ArrayList(definitionKeys.length);
//        String[] var6 = definitionKeys;
//        int var7 = definitionKeys.length;
//
//        for(int var8 = 0; var8 < var7; ++var8) {
//            String definitionKey = var6[var8];
//            if (definitionKey != null && !definitionKey.isEmpty()) {
//                Object key = PARSER.parseExpression(definitionKey).getValue(context, Object.class);
//                definitionKeyList.add(key);
//            }
//        }
//
//        return org.springframework.util.StringUtils.collectionToDelimitedString(definitionKeyList, ".", "", "");
//    }
//}